package demo.huodongbaoming.controller;

import demo.huodongbaoming.dto.ResponseResult;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import demo.huodongbaoming.service.DemoCircuitBreakerService;

/**
 * 熔断器演示控制器
 * 用于展示熔断器的工作原理和状态
 */
@RestController
@RequestMapping("/api/circuit-breaker")
public class CircuitBreakerDemoController {
    
    private static final Logger logger = LoggerFactory.getLogger(CircuitBreakerDemoController.class);

    @Autowired
    private CircuitBreakerFactory circuitBreakerFactory;
    
    @Autowired
    private CircuitBreakerRegistry circuitBreakerRegistry;

    @Autowired
    private demo.huodongbaoming.service.RemoteDemoService remoteDemoService;

    @Autowired
    private DemoCircuitBreakerService demoCircuitBreakerService;

    /**
     * 获取所有熔断器的状态
     * @return 熔断器状态列表
     */
    @GetMapping("/status")
    public ResponseResult<Map<String, Object>> getCircuitBreakersStatus() {
        logger.info("获取熔断器状态");
        Map<String, Object> status = new HashMap<>();
        
        // 获取默认熔断器状态
        CircuitBreaker defaultCircuitBreaker = circuitBreakerRegistry.circuitBreaker("default");
        Map<String, Object> defaultInfo = getCircuitBreakerInfo(defaultCircuitBreaker);
        status.put("default", defaultInfo);
        logger.info("默认熔断器状态: {}", defaultCircuitBreaker.getState());
        
        // 获取activity-service熔断器状态
        try {
            CircuitBreaker activityCircuitBreaker = circuitBreakerRegistry.circuitBreaker("activity-service");
            Map<String, Object> activityInfo = getCircuitBreakerInfo(activityCircuitBreaker);
            status.put("activity-service", activityInfo);
            logger.info("activity-service熔断器状态: {}", activityCircuitBreaker.getState());
        } catch (Exception e) {
            status.put("activity-service", "未找到熔断器");
            logger.warn("未找到activity-service熔断器: {}", e.getMessage());
        }
        
        return ResponseResult.success("获取熔断器状态成功", status);
    }
    
    /**
     * 模拟成功的服务调用
     * @return 成功响应
     */
    @GetMapping("/success")
    public ResponseResult<String> simulateSuccess() {
        logger.info("模拟成功的服务调用");
        return circuitBreakerFactory.create("demo-circuit-breaker")
                .run(() -> {
                    logger.info("服务调用成功执行");
                    return ResponseResult.success("服务调用成功", "操作成功完成");
                }, throwable -> {
                    logger.error("服务调用失败，触发降级: {}", throwable.getMessage());
                    return ResponseResult.fail(500, "服务降级: " + throwable.getMessage());
                });
    }
    
    /**
     * 模拟失败的服务调用
     * @return 失败响应
     */
    @GetMapping("/failure")
    public ResponseResult<String> simulateFailure() {
        logger.info("模拟失败的服务调用");
        return circuitBreakerFactory.create("demo-circuit-breaker")
                .run(() -> {
                    // 模拟服务调用失败
                    logger.info("模拟服务调用失败，抛出异常");
                    throw new RuntimeException("服务调用失败");
                }, throwable -> {
                    logger.error("服务调用失败，触发降级: {}", throwable.getMessage());
                    return ResponseResult.fail(500, "服务降级: " + throwable.getMessage());
                });
    }
    
    /**
     * 模拟超时的服务调用
     * @param delayMs 延迟毫秒数
     * @return 超时响应
     */
    @GetMapping("/timeout")
    public ResponseResult<String> simulateTimeout(@RequestParam(defaultValue = "5000") long delayMs) {
        logger.info("模拟超时的服务调用，延迟: {}ms", delayMs);
        return circuitBreakerFactory.create("demo-circuit-breaker")
                .run(() -> {
                    try {
                        // 模拟服务调用超时
                        logger.info("开始延迟 {}ms", delayMs);
                        Thread.sleep(delayMs);
                        logger.info("延迟结束，返回成功响应");
                        return ResponseResult.success("服务调用成功", "操作成功完成");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        logger.error("服务调用被中断: {}", e.getMessage());
                        throw new RuntimeException("服务调用被中断");
                    }
                }, throwable -> {
                    String message = throwable instanceof TimeoutException ? 
                            "服务调用超时" : "服务降级: " + throwable.getMessage();
                    logger.error("服务调用失败，触发降级: {}", message);
                    return ResponseResult.fail(500, message);
                });
    }
    
    /**
     * 强制打开熔断器
     * @return 操作结果
     */
    @PostMapping("/force-open")
    public ResponseResult<String> forceOpenCircuitBreaker() {
        logger.info("强制打开熔断器");
        try {
            CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("demo-circuit-breaker");
            CircuitBreaker.State previousState = circuitBreaker.getState();
            circuitBreaker.transitionToForcedOpenState();
            logger.info("熔断器状态从 {} 变为 {}", previousState, circuitBreaker.getState());
            return ResponseResult.success("熔断器已强制打开");
        } catch (Exception e) {
            logger.error("强制打开熔断器失败: {}", e.getMessage());
            return ResponseResult.fail(500, "操作失败: " + e.getMessage());
        }
    }
    
    /**
     * 强制关闭熔断器
     * @return 操作结果
     */
    @PostMapping("/force-close")
    public ResponseResult<String> forceCloseCircuitBreaker() {
        logger.info("强制关闭熔断器");
        try {
            CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("demo-circuit-breaker");
            CircuitBreaker.State previousState = circuitBreaker.getState();
            circuitBreaker.transitionToClosedState();
            logger.info("熔断器状态从 {} 变为 {}", previousState, circuitBreaker.getState());
            return ResponseResult.success("熔断器已强制关闭");
        } catch (Exception e) {
            logger.error("强制关闭熔断器失败: {}", e.getMessage());
            return ResponseResult.fail(500, "操作失败: " + e.getMessage());
        }
    }
    
    /**
     * 重置熔断器
     * @return 操作结果
     */
    @PostMapping("/reset")
    public ResponseResult<String> resetCircuitBreaker() {
        logger.info("重置熔断器");
        try {
            CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("demo-circuit-breaker");
            CircuitBreaker.State previousState = circuitBreaker.getState();
            circuitBreaker.reset();
            logger.info("熔断器已重置，状态从 {} 变为 {}", previousState, circuitBreaker.getState());
            return ResponseResult.success("熔断器已重置");
        } catch (Exception e) {
            logger.error("重置熔断器失败: {}", e.getMessage());
            return ResponseResult.fail(500, "操作失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取熔断器详细信息
     * @param circuitBreaker 熔断器实例
     * @return 熔断器信息Map
     */
    private Map<String, Object> getCircuitBreakerInfo(CircuitBreaker circuitBreaker) {
        Map<String, Object> info = new HashMap<>();
        CircuitBreaker.State state = circuitBreaker.getState();
        CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
        
        info.put("name", circuitBreaker.getName());
        info.put("state", state.name());
        info.put("failureRate", metrics.getFailureRate() + "%");
        info.put("slowCallRate", metrics.getSlowCallRate() + "%");
        info.put("numberOfSuccessfulCalls", metrics.getNumberOfSuccessfulCalls());
        info.put("numberOfFailedCalls", metrics.getNumberOfFailedCalls());
        info.put("numberOfSlowCalls", metrics.getNumberOfSlowCalls());
        info.put("numberOfNotPermittedCalls", metrics.getNumberOfNotPermittedCalls());
        
        return info;
    }

    /**
     * 熔断器真实远程服务调用示例
     * @param fail 是否强制失败
     * @return 响应结果
     */
    @GetMapping("/remote")
    public ResponseResult<String> remoteCall(@RequestParam(defaultValue = "false") boolean fail) {
        return remoteDemoService.callRemoteService(fail);
    }

    /**
     * 熔断器演示接口
     * @param fail 是否模拟失败
     * @return 响应结果
     */
    @GetMapping("/demo")
    public ResponseResult<String> demoCircuitBreaker(@RequestParam(defaultValue = "false") boolean fail) {
        return demoCircuitBreakerService.callWithCircuitBreaker(fail);
    }
} 